package com.mornd.gulimall.product.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mornd.gulimall.product.entity.*;
import com.mornd.gulimall.product.entity.vo.GroupWithAttrsVo;
import com.mornd.gulimall.product.mapper.AttrMapper;
import com.mornd.gulimall.product.service.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.ObjectFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;

import java.util.*;
import java.util.stream.Collectors;

import static com.mornd.gulimall.product.enums.AttrType.BASE;
import static org.springframework.util.StringUtils.hasText;

/**
 * <p>
 * 商品属性 服务实现类
 * </p>
 *
 * @author mornd
 * @since 2023-07-23
 */
@Service
public class AttrServiceImpl extends ServiceImpl<AttrMapper, Attr> implements IAttrService {
    @Resource
    private ICategoryService categoryService;
    @Resource
    private IAttrAttrgroupRelationService attrgroupRelationService;
    @Resource
    private IAttrGroupService attrGroupService;
    @Resource
    private ObjectFactory<IProductAttrValueService> productAttrValueService;

    @Override
    public IPage<Attr> list(Attr attr) {
        Page<Attr> page = new Page<>(attr.validPageNum(), attr.validPageSize());

        LambdaQueryWrapper<Attr> qw = Wrappers.<Attr>lambdaQuery().eq(attr.getCatelogId() != null, Attr::getCatelogId, attr.getCatelogId());
        qw.eq(attr.getAttrType() != null, Attr::getAttrType, attr.getAttrType());
        qw.like(hasText(attr.getAttrName()), Attr::getAttrName, attr.getAttrName());

        super.page(page, qw);

        for (Attr record : page.getRecords()) {
            // 查询关联分类
            Optional<Category> category = categoryService.getCacheById(record.getCatelogId());
            category.ifPresent(cat -> record.setCatelogName(cat.getName()));

            // 基本属性才关联分组数据
            if (BASE.ordinal() == record.getAttrType()) {
                AttrGroup group = getRelaGroup(record.getAttrId());
                if (group != null) {
                    record.setGroupName(group.getAttrGroupName());
                }
            }
        }
        return page;
    }

    /**
     * 获取关联的组信息
     *
     * @param attrId
     * @return
     */
    private AttrGroup getRelaGroup(Long attrId) {
        // 查询关联组
        // 目前只使用1对1关系，否则这里应该返回集合
        AttrAttrgroupRelation attrAttrgroupRelation = attrgroupRelationService.getOne(Wrappers.<AttrAttrgroupRelation>lambdaQuery().eq(AttrAttrgroupRelation::getAttrId, attrId));
        if (attrAttrgroupRelation != null) {
            return attrGroupService.getById(attrAttrgroupRelation.getAttrGroupId());
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean saveAttr(Attr attr) {
        attr.setAttrId(null);
        super.save(attr);

        // 基本属性保存分组关系
        if (BASE.ordinal() == attr.getAttrType()) {
            AttrAttrgroupRelation relation = new AttrAttrgroupRelation();
            relation.setAttrId(attr.getAttrId());
            relation.setAttrGroupId(attr.getGroupId());
            attrgroupRelationService.save(relation);
        }

        return true;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean updateAttr(Attr attr) {
        super.updateById(attr);

        // 基本属性修改分组关系
        if (BASE.ordinal() == attr.getAttrType()) {
            LambdaUpdateWrapper<AttrAttrgroupRelation> uw = Wrappers.<AttrAttrgroupRelation>lambdaUpdate()
                    .set(AttrAttrgroupRelation::getAttrGroupId, attr.getGroupId())
                    .eq(AttrAttrgroupRelation::getAttrId, attr.getAttrId());
            attrgroupRelationService.update(uw);
        }
        return true;
    }

    /**
     * 根据 id 查询
     */
    @Override
    public Attr get(Long id) {
        Attr attr = super.getById(id);
        if (attr != null) {
            if (BASE.ordinal() == attr.getAttrType()) {
                AttrGroup group = getRelaGroup(id);
                if (group != null) {
                    attr.setGroupId(group.getAttrGroupId());
                }
            }

            List<Long> from = categoryService.from(attr.getCatelogId());
            attr.setCatelogFrom(from);
        }
        return attr;
    }

    /**
     * 删除属性和分组
     *
     * @param ids
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean relationRemove(Long[] ids) {

        super.removeByIds(Arrays.asList(ids));

        return attrgroupRelationService.remove(Wrappers.<AttrAttrgroupRelation>lambdaQuery()
                .in(AttrAttrgroupRelation::getAttrId, ids));
    }

    /**
     * 根据 groupId 查询 规格参数 列表
     *
     * @param groupId
     * @return
     */
    @Override
    public List<Attr> specByGroupId(Long groupId) {
        List<AttrAttrgroupRelation> list = attrgroupRelationService.list(Wrappers.<AttrAttrgroupRelation>lambdaQuery().eq(AttrAttrgroupRelation::getAttrGroupId, groupId));
        Set<Long> ids = list.stream().map(AttrAttrgroupRelation::getAttrId).collect(Collectors.toSet());
        if (ids.isEmpty()) {
            return Collections.emptyList();
        }
        return super.listByIds(ids);
    }

    /**
     * 根据分类id查询 attrGroup 和其对应的 attrs 根据分类id查询规格参数(基本属性)
     * 如果 spuId 有值那么就回显 spu 的值
     *
     * @param catId
     * @param spuId
     * @return
     */
    @Override
    public List<GroupWithAttrsVo> specByCatId(Long catId, String spuId) {
        List<AttrGroup> list = attrGroupService.list(Wrappers.<AttrGroup>lambdaQuery().eq(AttrGroup::getCatelogId, catId));

        List<GroupWithAttrsVo> groupWithAttrsVos = list.stream().map(i -> {
            GroupWithAttrsVo vo = new GroupWithAttrsVo();
            BeanUtils.copyProperties(i, vo);
            List<Attr> attrs = this.specByGroupId(i.getAttrGroupId());
            vo.setAttrs(attrs);
            return vo;
        }).collect(Collectors.toList());

        if (!StringUtils.hasText(spuId)) {
            return groupWithAttrsVos;
        } else {

            // 回显值
            List<ProductAttrValue> spuAttrs = productAttrValueService.getObject().list(Wrappers.<ProductAttrValue>lambdaQuery().eq(ProductAttrValue::getSpuId, spuId));

            if (CollUtil.isNotEmpty(groupWithAttrsVos) && CollUtil.isNotEmpty(spuAttrs)) {
                groupWithAttrsVos.forEach(gwa -> {
                    if (CollUtil.isNotEmpty(gwa.getAttrs())) {
                        for (ProductAttrValue spuAttr : spuAttrs) {
                            for (Attr attr : gwa.getAttrs()) {
                                if(attr.getAttrId().equals(spuAttr.getAttrId())) {
                                    // 回显值
                                    attr.setValue(spuAttr.getAttrValue());
                                    // 回显快速显示
                                    attr.setShowDesc(spuAttr.getQuickShow());
                                    break;
                                }
                            }
                        }

//                        gwa.getAttrs().forEach(attr -> {
//                            spuAttrs.stream()
//                                    .filter(spuAttr -> attr.getAttrId().equals(spuAttr.getAttrId()))
//                                    .findFirst()
//                                    .ifPresent(spuAttr -> {
//                                        // 回显值
//                                        attr.setValue(spuAttr.getAttrValue());
//                                        // 回显快速显示
//                                        attr.setShowDesc(spuAttr.getQuickShow());
//                                    });
//                        });
                    }
                });
            }

            return groupWithAttrsVos;
        }
    }

    /**
     * 根据 spuId 查询其对应的所有属性分组及其分组下的所有属性
     *
     * @param spuId
     * @return
     */
    @Override
    public List getGroupsAndAttrsBySpuId(Long spuId) {
        return baseMapper.getGroupsAndAttrsBySpuId(spuId);
    }
}
